/**
 * @author liuzy
 * 数据源代理类：根据登录用户所登录系统获取数据源
 */
package com.wjf.birdfish.util;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DataSourceProxy implements DataSource {
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	private Map<String, DataSource> ds;
	
	private String defaultDataSource;
	
	@Override
	public PrintWriter getLogWriter() throws SQLException {
		return this.getDataSourceProxy().getLogWriter();
	}

	@Override
	public void setLogWriter(PrintWriter out) throws SQLException {
		Collection<DataSource> dsList = ds.values();
		for (DataSource ds: dsList) {
			ds.setLogWriter(out);
		}
	}

	@Override
	public void setLoginTimeout(int seconds) throws SQLException {
		Collection<DataSource> dsList = ds.values();
		for (DataSource ds: dsList) {
			ds.setLoginTimeout(seconds);
		}
	}

	@Override
	public int getLoginTimeout() throws SQLException {
		return this.getDataSourceProxy().getLoginTimeout();
	}

	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		return this.getDataSourceProxy().unwrap(iface);
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		return this.getDataSourceProxy().isWrapperFor(iface);
	}

	@Override
	public Connection getConnection() throws SQLException {
		if (this.getDataSourceProxy() == null) {
			return null;
		}
		return this.getDataSourceProxy().getConnection();
	}

	@Override
	public Connection getConnection(String username, String password)
			throws SQLException {
		return this.getDataSourceProxy().getConnection(username, password);
	}
	
	/**
	 * 根据当前登录用户信息获取数据源
	 */
	private DataSource getDataSourceProxy() {
		SecurityContext context = SecurityContextHolder.getContext();
		DataSource ds = ds().get(getDataSource(context));
		if (ds == null) {
			String error = "Can't find datasource: " + getDataSource(context) + ".";
			logger.error(error);
			throw new RuntimeException(error);
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Find datasource: {}.", getDataSource(context));
		}
		return ds;
	}

	private String getDataSource(SecurityContext context) {
		return context == null ? getDefaultDataSource(): context.getArea();
	}
	
	private Map<String, DataSource> ds() {
		if (this.ds == null) {
			this.ds = new HashMap<String, DataSource>();
		}
		return this.ds;
	}

	public void setDs(Map<String, DataSource> ds) {
		this.ds = ds;
	}

	public String getDefaultDataSource() {
		return defaultDataSource;
	}

	public void setDefaultDataSource(String defaultDataSource) {
		this.defaultDataSource = defaultDataSource;
	}
	
}
